package com.gd.iot.energy.util;


import cn.hutool.core.date.CalendarUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.gd.iot.energy.code.ResponseCode;
import com.gd.iot.energy.consts.SystemConsts;
import com.gd.iot.energy.exception.MyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author kris
 */
@Slf4j
public class CustomDateUtil extends DateUtil {
    public static final String MONTH_PATTERN = "yyyy-MM-dd";
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String LONG_PATTERN = "yyyyMMddHHmm";

    public static final String FULL_DATE = "yyyy-MM-dd HH:mm:ss";
    public static final String HOUR_MINUTE_DATE = "yyyy-MM-dd HH:mm";
    public static final String YEAR_MONTH = "yyyyMM";
    public static final String YEAR_AND_MONTH = "yyyy-MM";
    public static final String YEAR_PATTERN = "yyyy";
    public static final String MONTH_DAY = "MM-dd";


    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(String str, String pattern) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        return parseDate(str, pattern);
    }

    public static Date addDays(final Date date, final int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    private static Date add(Date date, int calendarField, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 解析excel日期
     *
     * @param days
     * @return
     */
    public static Date parseExcelDate(String days) {
        Calendar calendar = new GregorianCalendar(1900, 0, 0);
        Date d = calendar.getTime();
        return addDays(d, Double.valueOf(days).intValue() - 1);
    }

    public static Date getEndOfDay(String date) {
        SimpleDateFormat sdf = new SimpleDateFormat(MONTH_PATTERN);
        try {
            Date date1 = sdf.parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date1);
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
            return calendar.getTime();
        } catch (ParseException e) {
            throw new MyException(ResponseCode.PARAMETER_ERROR);
        }
    }

    /**
     * 根据 周期获取开始和结束日期
     *
     * @param type
     * @param date
     * @return
     */
    public static List<String> dataFormatCycle(final String type, final String date) {
        final List<String> list = new ArrayList<>();
        String begin = null;
        String end = null;
        final Calendar cal = Calendar.getInstance();
        final int year = cal.get(Calendar.YEAR);
        final SystemConsts.DATE_CYCLE_TYPE dateCycleType = SystemConsts.DATE_CYCLE_TYPE.getEnumByValue(type);
        if (dateCycleType == null || StrUtil.isBlank(date)) {
            list.add(begin);
            list.add(end);
            return list;
        }
        switch (dateCycleType) {
            case DAY: {
                begin = date + " 00:00:00";
                end = date + " 23:59:59";
                list.add(begin);
                list.add(end);
                return list;
            }
            case MONTH: {
                begin = date + "-01 00:00:00";
                end = date + "-31 23:59:59";
                list.add(begin);
                list.add(end);
                return list;
            }
            case QUARTER: {
                if (SystemConsts.QUARTER_TYPE.FIRST.value.equals(date)) {
                    begin = year + "-01-01 00:00:00";
                    end = year + "-03-31 23:59:59";
                    list.add(begin);
                    list.add(end);
                } else if (SystemConsts.QUARTER_TYPE.SECOND.value.equals(date)) {
                    begin = year + "-04-01 00:00:00";
                    end = year + "-06-31 23:59:59";
                    list.add(begin);
                    list.add(end);
                } else if (SystemConsts.QUARTER_TYPE.THIRD.value.equals(date)) {
                    begin = year + "-07-01 00:00:00";
                    end = year + "-09-31 23:59:59";
                    list.add(begin);
                    list.add(end);
                } else {
                    begin = year + "-10-01 00:00:00";
                    end = year + "-12-31 23:59:59";
                    list.add(begin);
                    list.add(end);
                }
            }
            case YEAR: {
                begin = date + "-01-01 00:00:00";
                end = date + "-12-31 23:59:59";
                list.add(begin);
                list.add(end);
                return list;
            }
            default:
                break;
        }
        return list;
    }


    /**
     * 获取同比开始结束日期
     *
     * @param dateCycleType
     * @param date
     * @param statisticsType
     * @return
     */
    public static Map<String, String> getBeginAndEndDate(final SystemConsts.DATE_CYCLE_TYPE dateCycleType,
                                                         final String date,
                                                         SystemConsts.StatisticsType statisticsType) {
        Map<String, String> map = new HashMap<>();
        try {
            Calendar calendar = Calendar.getInstance();
            Date beginDate = new Date();
            Date endDate = new Date();
            if (dateCycleType == SystemConsts.DATE_CYCLE_TYPE.MONTH) {
                calendar.setTime(DateUtil.parseDate(date + "-01"));
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                beginDate = CalendarUtil.beginOfDay(calendar).getTime();
                endDate = CalendarUtil.endOfMonth(calendar).getTime();
            } else if (dateCycleType == SystemConsts.DATE_CYCLE_TYPE.YEAR) {
                calendar.set(Calendar.YEAR, Integer.parseInt(date));
                beginDate = CalendarUtil.beginOfYear(calendar).getTime();
                endDate = CalendarUtil.endOfYear(calendar).getTime();
            } else if (dateCycleType == SystemConsts.DATE_CYCLE_TYPE.QUARTER) {
                calendar.setTime(new Date());
                calendar.set(Calendar.MONTH, Integer.parseInt(date) * 3);
                beginDate = CalendarUtil.beginOfQuarter(calendar).getTime();
                endDate = CalendarUtil.endOfQuarter(calendar).getTime();
            } else if (dateCycleType == SystemConsts.DATE_CYCLE_TYPE.DAY) {
                calendar.setTime(DateUtil.parseDate(date));
                beginDate = CalendarUtil.beginOfDay(calendar).getTime();
                endDate = CalendarUtil.endOfDay(calendar).getTime();
            }
            String beginDateStr = DateUtil.formatDateTime(beginDate);
            String endDateStr = DateUtil.formatDateTime(endDate);
            map.put("begin", DateUtil.formatDate(beginDate));
            map.put("beginDate", beginDateStr);
            map.put("end", DateUtil.formatDate(endDate));
            map.put("endDate", endDateStr);
            if (statisticsType.equals(SystemConsts.StatisticsType.YEAR_TO_YEAR)) {
                getLastYearDate(map, beginDateStr);
            } else {
                getLastMonthDate(map, beginDate, endDate, dateCycleType);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MyException(ResponseCode.PARAMETER_ERROR);
        }
        return map;
    }

    /**
     * 环比日期
     *
     * @param map
     * @param beginDate
     * @param endDate
     * @param dateCycleType
     */
    private static void getLastMonthDate(Map<String, String> map, Date beginDate, Date endDate, SystemConsts.DATE_CYCLE_TYPE dateCycleType) {
        Calendar calendarBegin = Calendar.getInstance();
        calendarBegin.setTime(beginDate);
        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.setTime(endDate);
        switch (dateCycleType) {
            case DAY:
                calendarBegin.add(Calendar.DAY_OF_MONTH, -1);
                calendarEnd.add(Calendar.DAY_OF_MONTH, -1);
                break;
            case MONTH:
                calendarBegin.add(Calendar.MONTH, -1);
                calendarEnd.add(Calendar.MONTH, -1);
                break;
            case QUARTER:
                calendarBegin.add(Calendar.MONTH, -3);
                calendarEnd.add(Calendar.MONTH, -3);
                break;
            case YEAR:
                calendarBegin.add(Calendar.YEAR, -1);
                calendarEnd.add(Calendar.YEAR, -1);
                break;
            default:
        }
        map.put("lastBeginDate", DateUtil.formatDateTime(calendarBegin.getTime()));
        map.put("lastEndDate", DateUtil.formatDateTime(calendarEnd.getTime()));
        map.put("lastBegin", DateUtil.formatDate(calendarBegin.getTime()));
        map.put("lastEnd", DateUtil.formatDate(calendarEnd.getTime()));
    }

    /**
     * 设置去年的时间
     *
     * @param map
     * @param beginDateStr
     */
    private static void getLastYearDate(Map<String, String> map, String beginDateStr) {
        final int year = Integer.parseInt(beginDateStr.substring(0, 4)) - 1;
        map.put("lastBegin", year + map.get("beginDate").substring(4, 10));
        map.put("lastBeginDate", year + map.get("beginDate").substring(4));
        map.put("lastEnd", year + map.get("endDate").substring(4, 10));
        map.put("lastEndDate", year + map.get("endDate").substring(4));
    }

    /**
     * 获取两个日期间的所有日期
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public static List<String> getDatesBetweenTwoDate(final String beginTime, final String endTime) {
        final List<String> lDate = new ArrayList<>();
        lDate.add(beginTime);
        final Calendar cal = Calendar.getInstance();
        final Date dBegin = DateUtil.parseDate(beginTime);
        final Date dEnd = DateUtil.parseDate(endTime);
        cal.setTime(dBegin);
        final boolean bContinue = true;
        while (bContinue) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
            if (!dEnd.after(cal.getTime())) {
                break;
            }
            lDate.add(DateUtil.formatDate(cal.getTime()));
        }
        lDate.add(endTime);
        return lDate;
    }

    /**
     * 根据类型获取时间
     *
     * @param dateCycleType
     * @param startDate
     * @param endDate
     * @return
     */
    public static Map<String, String> getStartAndEndTimeByType(SystemConsts.DATE_CYCLE_TYPE dateCycleType,
                                                               String startDate, String endDate) {
        Map<String, String> map = new HashMap<>(2);
        try {
            Date start = null;
            Date end = null;
            if (SystemConsts.DATE_CYCLE_TYPE.DAY.equals(dateCycleType)) {
                start = DateUtil.beginOfDay(CustomDateUtil.parseDate(startDate));
                end = DateUtil.beginOfDay(CustomDateUtil.parseDate(endDate));
            } else if (SystemConsts.DATE_CYCLE_TYPE.MONTH.equals(dateCycleType)) {
                start = DateUtil.beginOfMonth(CustomDateUtil.parseDate(startDate + "-01"));
                end = DateUtil.endOfMonth(CustomDateUtil.parseDate(endDate + "-01"));
            } else if (SystemConsts.DATE_CYCLE_TYPE.YEAR.equals(dateCycleType)) {
                start = DateUtil.beginOfYear(CustomDateUtil.parseDate(startDate + "-01-01"));
                end = DateUtil.endOfYear(CustomDateUtil.parseDate(endDate + "-01-01"));
            } else {
                throw new MyException(ResponseCode.PARAMETER_ERROR);
            }
            map.put("beginDate", DateUtil.formatDate(start));
            map.put("endDate", DateUtil.formatDate(end));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MyException(ResponseCode.PARAMETER_ERROR);
        }
        return map;

    }
}
